package ru.bragnikita.utils.swing.dbpanel;

import com.google.common.collect.Lists;
import ru.bragnikita.utils.swing.utils.PanelTest;
import ru.bragnikita.utils.swing.widget.*;
import ru.bragnikita.utils.swing.widget.field.TextField;
import ru.bragnikita.utils.swing.widget.mult.ItemAdapter;
import ru.bragnikita.utils.swing.widget.mult.ItemEvent;
import ru.bragnikita.utils.swing.widget.mult.WtTextComboBox;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author Nikita.Brazhnikov
 */
public class DatabasePanel {

    private JPanel panel;

    private WtTextField url;
    private WtTextField sid;
    private WtTextField port;
    private WtTextField username;
    private WtTextField password;
    private MultiLineLabel databaseTestLabel;
    private JButton btnSave;
    private JButton btnDelete;
    private WtTextComboBox<DatabaseItem> databases;

    private Map<String, Widget> widgetMap = new TreeMap<>();

    private DatabaseItem newItem = new DatabaseItem("Add new...");
    private List<DatabaseItem> model;

    public DatabasePanel() {
        panel = new JPanel(new GridBagLayout());

        url = new WtTextField(new TextField("url", "URL").withLength(15));
        sid = new WtTextField(new TextField("sid", "SID").withLength(4));
        port = new WtTextField(new TextField("port", "Port").withLength(4));
        username = new WtTextField(new TextField("username", "Username").withLength(10));
        password = new WtTextField(new TextField("password", "Password").withLength(10));
        databases = new WtTextComboBox<>(new TextField("database", "Databases") {
            @Override
            public String getAsString(Object value) {
                return ((DatabaseItem) value).getName();
            }
        });
        databases.getEventSupport().addListener(new ItemAdapter<DatabaseItem>() {
            @Override
            public void onSelect(ItemEvent<DatabaseItem> itemEvent) {
                DatabaseItem item = itemEvent.getItem();
                if (item != newItem)
                    mapFrom(item);
            }
        });
        btnSave = new JButton(new AbstractAction() {
            {
                putValue(AbstractAction.NAME, "Save");
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                saveOrUpdate();
            }
        });
        btnDelete = new JButton(new AbstractAction() {
            {
                putValue(AbstractAction.NAME, "Delete");
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                delete();
            }
        });
        putWidget(url, sid, port, username, password);
        layout();
    }

    private void putWidget(Widget... widget) {
        for (Widget w : widget) {
            widgetMap.put(w.getId(), w);
        }
    }

    private String getString(String id) {
        final Widget widget = widgetMap.get(id);
        return widget != null ? widget.getAsString() : null;
    }

    private Object getValue(String id) {
        final Widget widget = widgetMap.get(id);
        return widget != null ? widget.getValue() : null;
    }

    private void setValue(String id, String value) {
        final Widget widget = widgetMap.get(id);
        if (widget != null) {
            widget.setValue(value);
        }
    }


    private void saveOrUpdate() {
        DatabaseItem currentItem = databases.getSelectedValue();
        if (currentItem == null)
            return;
        if (currentItem == newItem) {
            String name = new DatabaseNameDialog(null).request();
            if (name == null)
                return;
            DatabaseItem newItem = new DatabaseItem(name);
            mapTo(newItem);
            model.add(newItem);
            setDatabases(model);
            databases.setSelected(newItem);
        } else {
            mapTo(currentItem);
        }
    }

    private void delete() {
        DatabaseItem currentItem = databases.getSelectedValue();
        if (currentItem == newItem)
            return;
        model.remove(currentItem);
        setDatabases(model);
        final DatabaseItem first = databases.getFirst();
        databases.setSelected(first);
        databases.fireSelectionChanged(null, first);
    }

    private DatabaseItem mapTo(DatabaseItem to) {
        to.setUrl(getString("url"));
        to.setPort(getString("port"));
        to.setPassword(getString("password"));
        to.setSid(getString("sid"));
        to.setUsername(getString("username"));
        return to;
    }

    private void mapFrom(DatabaseItem from) {
        setValue("url", from.getUrl());
        setValue("port", from.getPort());
        setValue("username", from.getUsername());
        setValue("password", from.getPassword());
        setValue("sid", from.getPassword());
    }

    private void layout() {
        GridBagConstraints c = new GridBagConstraints();
        c.ipadx = 3;
        c.ipady = 5;
        c.insets = new Insets(5, 0, 5, 0);
        c.fill = GridBagConstraints.HORIZONTAL;

        c.gridy = 0;
        c.gridx = 1;
        c.gridwidth = 3;
        panel.add(databases.getComponent(), c);
        c.gridx += 3;
        c.gridwidth = 1;
        panel.add(btnSave, c);
        c.gridx++;
        panel.add(btnDelete, c);

        c.gridy++;
        c.gridx = 0;
        c.gridwidth = 1;
        c.anchor = GridBagConstraints.LINE_END;
        panel.add(url.getLabel(), c);
        c.gridx++;
        c.gridwidth = 2;
        c.anchor = GridBagConstraints.LINE_START;
        panel.add(url.getComponent(), c);
        c.gridx += 2;
        c.gridwidth = 1;
        c.anchor = GridBagConstraints.LINE_END;
        panel.add(port.getLabel(), c);
        c.gridx++;
        c.anchor = GridBagConstraints.LINE_START;
        panel.add(port.getComponent(), c);
        c.gridx++;
        c.anchor = GridBagConstraints.LINE_END;
        panel.add(sid.getLabel(), c);
        c.gridx++;
        c.gridwidth = 1;
        c.anchor = GridBagConstraints.LINE_START;
        panel.add(sid.getComponent(), c);

        c.gridy++;
        c.gridx = 0;
        c.gridwidth = 2;
        c.anchor = GridBagConstraints.LINE_END;
        panel.add(username.getLabel(), c);
        c.gridx += 2;
        c.gridwidth = 1;
        c.anchor = GridBagConstraints.LINE_START;
        panel.add(username.getComponent(), c);
        c.gridx += 1;
        c.gridwidth = 2;
        c.anchor = GridBagConstraints.LINE_END;
        panel.add(password.getLabel(), c);
        c.gridx += 2;
        c.anchor = GridBagConstraints.LINE_START;
        panel.add(password.getComponent(), c);


    }

    public JPanel getPanel() {
        return panel;
    }

    public void setDatabases(List<DatabaseItem> items) {
        this.model = items;
        List<DatabaseItem> extendedList = Lists.newLinkedList(items);
        extendedList.set(0, newItem);
        this.databases.setModel(extendedList);
    }

    public static void main(String[] args) {
        DatabasePanel dbPanel = new DatabasePanel();

        List<DatabaseItem> items = Lists.newLinkedList();
        for (int i = 0; i < 5; i++) {
            items.add(new DatabaseItem("Item " + Integer.valueOf(i)));
        }
        dbPanel.setDatabases(items);
        PanelTest.display(dbPanel.getPanel());
    }


}
